package antoauth

import (
	"context"
	"errors"
	"net/http"

	"git.oschina.net/antlinker/antevent/server/bus"

	"git.oschina.net/antlinker/antevent/server/engine"
	"git.oschina.net/antlinker/antevent/server/evtlog"

	"github.com/antlinker/sdk/asapi"
	"github.com/goadesign/goa"
	goaclient "github.com/goadesign/goa/client"
)

const (
	// ClientIDKey 请求服务的客户端id键名
	ClientIDKey = "cliid"
)

// ErrAntOAuthFailed 认证失败
var ErrAntOAuthFailed = goa.NewErrorClass("antoAuth_auth_failed", 401)

// New 创建antoauth中间件
func New(cfg *asapi.Config, all *bus.AllBus) goa.Middleware {
	asapi.InitAPI(cfg)
	auth := all.Auth()
	middleware, _ := goa.NewMiddleware(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {

		evtlog.Info("认证进入这里认证")
		token := r.Header.Get("Authorization")
		if len(token) > 7 {
			token = token[7:]
		} else {
			return ErrAntOAuthFailed("Authentication failed")
		}
		evtlog.Info("token==%s", token)
		rs, err := auth.Verfiy(token)
		if err != nil {
			evtlog.Info("认证失败:%+v", err)
			return ErrAntOAuthFailed("Authentication failed 1")
		}
		if !rs {
			return ErrAntOAuthFailed("Authentication failed 2")
		}

		return nil
	})
	return middleware
}

// CreateAuthHookServerHandler 创建一个事件引擎向钩子服务器发送事件认证函数
func CreateAuthHookServerHandler() engine.AuthHookServerHandler {
	return authHookServer
}
func authHookServer(req *http.Request) {
	token, r := asapi.GetToken()
	if r != nil {
		evtlog.Error("获取令牌失败")
	}
	req.Header.Set("Authorization", "Bearer "+token)
	evtlog.Debug("接收令牌:", token)
}

// AuthHookClient 回调钩子客户端验证令牌
func AuthHookClient(req *http.Request) error {
	token := req.Header.Get("Authorization")
	if len(token) > 7 {
		token = token[7:]
	} else {
		return ErrAntOAuthFailed("Authentication failed")
	}
	_, _, err := asapi.VerifyToken(token)
	if err != nil {
		return ErrAntOAuthFailed("Authentication failed")
	}
	return nil
}

// SignerOption 参数
type SignerOption struct {
	AuthCfg *asapi.Config

	JWTSignedKey string
}

// NewSigner 创建antoauth中间件
func NewSigner(opt SignerOption) goaclient.Signer {
	asapi.InitAPI(opt.AuthCfg)

	return authSigner{auth: bus.CreateAuth(opt.JWTSignedKey, "")}
}

type authSigner struct {
	auth bus.Auth
}

func (s authSigner) Sign(req *http.Request) error {

	token, r := s.auth.CreProdToken()
	if r != nil {
		return errors.New("获取令牌失败")
	}
	req.Header.Set("Authorization", "Bearer "+token)
	evtlog.Debug("发送令牌:", token)
	return nil
}
